using System;
using System.ServiceModel;

namespace Salient.ServiceModel
{
    /// <summary>
    /// This class contains extension methods related to WCF services.
    /// </summary>
    public static class ServiceExtensions
    {
        /// <summary>
        /// Extends ICommunicationObject to handle exceptions thrown by the Close method
        /// by calling the Abort method to ensure the transition to the Closed state.
        /// </summary>
        /// <param name="service">
        /// The service to Close or Abort then Dispose.
        /// </param>
        public static void CloseOrAbort(this ICommunicationObject service)
        {
            // do not throw null reference exception
            if (service == null)
            {
                return;
            }
            if (service.State != CommunicationState.Closed
                && service.State != CommunicationState.Closing)
            {
                try
                {
                    // if Close attempts closing the session on the server and there
                    // is a problem during the roundtrip it will throw an exception
                    // and never transition to the Closed state
                    service.Close();
                }
                catch (CommunicationException)
                {
                    // not closed - call Abort to transition to the closed state
                    service.Abort();
                }
                catch (TimeoutException)
                {
                    // not closed - call Abort to transition to the closed state
                    service.Abort();
                }
                catch (Exception)
                {
                    // not closed - call Abort to transition to the closed state
                    service.Abort();
                    // this is an unexpected exception type - throw
                    throw;
                }
            }
        }
    }
}